package com.ruoyi.pos.service.impl.cashier;

import com.ruoyi.pos.domain.cashier.PosCashier;
import com.ruoyi.pos.domain.dto.cashier.request.CashierLoginRequest;
import com.ruoyi.pos.domain.dto.cashier.request.PasswordChangeRequest;
import com.ruoyi.pos.domain.dto.cashier.response.CashierLoginResponse;
import com.ruoyi.pos.domain.dto.cashier.response.PasswordChangeResponse;
import com.ruoyi.pos.mapper.cashier.PosCashierMapper;
import com.ruoyi.pos.service.cashier.IPosCashierService;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * POS收银员Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-01-30
 */
@Service
@Transactional(transactionManager = "posTransactionManager")
public class PosCashierServiceImpl implements IPosCashierService {

    private static final Logger logger = LoggerFactory.getLogger(PosCashierServiceImpl.class);

    @Autowired
    private PosCashierMapper posCashierMapper;

    /**
     * 收银员登录
     * 
     * @param request 登录请求
     * @return 登录响应
     */
    @Override
    public CashierLoginResponse cashierLogin(CashierLoginRequest request) {
        CashierLoginResponse response = new CashierLoginResponse();
        
        try {
            logger.info("收银员登录请求, cashierCode: {}", request.getCashierCode());
            
            // 根据收银员编码查询收银员信息
            PosCashier cashier = posCashierMapper.selectPosCashierByCode(request.getCashierCode());
            
            if (cashier == null) {
                logger.warn("收银员不存在, cashierCode: {}", request.getCashierCode());
                response.setSuccess(false);
                response.setMessage("收银员不存在");
                return response;
            }
            
            // 验证密码（使用BCrypt加密比较）
            if (!SecurityUtils.matchesPassword(request.getPassword(), cashier.getPassword())) {
                logger.warn("收银员密码错误, cashierCode: {}", request.getCashierCode());
                response.setSuccess(false);
                response.setMessage("密码错误");
                return response;
            }
            
            // 检查收银员状态
            if (!"1".equals(cashier.getStatus())) {
                logger.warn("收银员账号已禁用, cashierCode: {}", request.getCashierCode());
                response.setSuccess(false);
                response.setMessage("收银员账号已禁用");
                return response;
            }
            
            // 生成登录token
            String token = generateToken();
            
            // 更新最后登录时间和登录IP
            cashier.setLastLoginTime(new Date());
            cashier.setLastLoginIp(request.getLoginIp());
            cashier.setIsOnline("1"); // 设置为在线状态
            posCashierMapper.updatePosCashier(cashier);
            
            // 构建响应
            response.setSuccess(true);
            response.setMessage("登录成功");
            response.setCashierId(cashier.getCashierId());
            response.setCashierCode(cashier.getCashierCode());
            response.setCashierName(cashier.getCashierName());
            response.setAccessToken(token);
            response.setLoginTime(new Date());
            
            logger.info("收银员登录成功, cashierCode: {}, cashierName: {}", 
                cashier.getCashierCode(), cashier.getCashierName());
            response.setDeviceId(request.getDeviceId());
            
        } catch (Exception e) {
            logger.error("收银员登录失败, cashierCode: {}, error: {}", 
                request.getCashierCode(), e.getMessage(), e);
            response.setSuccess(false);
            response.setMessage("登录失败: " + e.getMessage());
        }
        
        return response;
    }

    /**
     * 收银员登出
     * 
     * @param cashierId 收银员ID
     * @param deviceId 设备ID
     * @return 是否成功
     */
    @Override
    public boolean cashierLogout(Long cashierId, Long deviceId) {
        try {
            PosCashier cashier = new PosCashier();
            cashier.setCashierId(cashierId);
            cashier.setIsOnline("0"); // 设置为离线状态
            cashier.setCurrentDeviceCode(null); // 清空当前设备
            
            return posCashierMapper.updatePosCashier(cashier) > 0;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 切换收银员
     * 
     * @param oldCashierId 原收银员ID
     * @param newCashierId 新收银员ID
     * @param deviceId 设备ID
     * @return 是否成功
     */
    @Override
    public boolean switchCashier(Long oldCashierId, Long newCashierId, Long deviceId) {
        // 简化实现：切换收银员功能暂不实现，返回true表示允许切换
        // 实际业务中，如果需要可以添加：登出旧收银员、登录新收银员的逻辑
        return true;
    }

    /**
     * 获取当前收银员信息
     * 
     * @param deviceId 设备ID
     * @return 收银员信息
     */
    @Override
    public CashierLoginResponse getCurrentCashier(Long deviceId) {
        // 根据设备ID查找当前登录的收银员
        // 这里简化实现，实际应该通过设备ID查询
        return new CashierLoginResponse();
    }

    /**
     * 验证收银员设备权限
     * 
     * @param cashierId 收银员ID
     * @param deviceId 设备ID
     * @return 是否有权限
     */
    @Override
    public boolean checkCashierDevicePermission(Long cashierId, Long deviceId) {
        try {
            // 查询收银员设备权限关系
            // 这里简化实现，实际应该查询 pos_cashier_device 表
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 验证收银员柜组权限
     * 
     * @param cashierId 收银员ID
     * @param groupId 柜组ID
     * @return 是否有权限
     */
    @Override
    public boolean checkCashierGroupPermission(Long cashierId, Long groupId) {
        try {
            // 查询收银员柜组权限关系
            // 这里简化实现，实际应该查询 pos_cashier_group 表
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 修改收银员密码
     * 
     * @param request 密码修改请求
     * @return 密码修改响应
     */
    @Override
    public PasswordChangeResponse changePassword(PasswordChangeRequest request) {
        PasswordChangeResponse response = new PasswordChangeResponse();
        
        try {
            logger.info("收银员修改密码请求, cashierCode: {}", request.getCashierCode());
            
            // 根据收银员编码查询收银员
            PosCashier cashier = posCashierMapper.selectPosCashierByCode(request.getCashierCode());
            if (cashier == null) {
                logger.warn("收银员不存在, cashierCode: {}", request.getCashierCode());
                response.setSuccess(false);
                response.setMessage("收银员不存在");
                return response;
            }
            
            // 验证原密码（使用BCrypt加密比较）
            if (!SecurityUtils.matchesPassword(request.getOldPassword(), cashier.getPassword())) {
                logger.warn("原密码错误, cashierCode: {}", request.getCashierCode());
                response.setSuccess(false);
                response.setMessage("原密码错误");
                return response;
            }
            
            // 验证新密码和确认密码是否一致
            if (!StringUtils.equals(request.getNewPassword(), request.getConfirmPassword())) {
                logger.warn("新密码和确认密码不一致, cashierCode: {}", request.getCashierCode());
                response.setSuccess(false);
                response.setMessage("新密码和确认密码不一致");
                return response;
            }
            
            // 更新密码（使用BCrypt加密存储）
            String encryptedPassword = SecurityUtils.encryptPassword(request.getNewPassword());
            cashier.setPassword(encryptedPassword);
            cashier.setPwdUpdateDate(new Date());
            cashier.setUpdateTime(new Date());
            
            int result = posCashierMapper.updatePosCashier(cashier);
            response.setSuccess(result > 0);
            response.setMessage(result > 0 ? "密码修改成功" : "密码修改失败");
            
            if (result > 0) {
                logger.info("收银员密码修改成功, cashierCode: {}", request.getCashierCode());
            }
            
        } catch (Exception e) {
            logger.error("收银员密码修改失败, cashierCode: {}, error: {}", 
                request.getCashierCode(), e.getMessage(), e);
            response.setSuccess(false);
            response.setMessage("密码修改失败: " + e.getMessage());
        }
        
        return response;
    }

    /**
     * 生成登录token
     * 
     * @return token
     */
    private String generateToken() {
        return UUID.randomUUID().toString().replace("-", "");
    }

    // ==================== Mapper基础方法实现 ====================

    @Override
    public List<PosCashier> selectPosCashierList(PosCashier posCashier) {
        return posCashierMapper.selectPosCashierList(posCashier);
    }

    @Override
    public PosCashier selectPosCashierByCashierId(Long cashierId) {
        return posCashierMapper.selectPosCashierById(cashierId);
    }

    @Override
    public int insertPosCashier(PosCashier posCashier) {
        posCashier.setCreateTime(new Date());
        posCashier.setUpdateTime(new Date());
        posCashier.setIsOnline("0"); // 默认离线
        posCashier.setPwdUpdateDate(new Date());
        // 设置默认状态
        if (posCashier.getStatus() == null) {
            posCashier.setStatus("0"); // 默认正常
        }
        if (posCashier.getIsFirstLogin() == null) {
            posCashier.setIsFirstLogin("1"); // 默认首次登录
        }
        return posCashierMapper.insertPosCashier(posCashier);
    }

    @Override
    public int updatePosCashier(PosCashier posCashier) {
        logger.info("更新收银员, cashierId: {}", posCashier.getCashierId());
        
        // 如果要更新密码，需要加密
        if (StringUtils.isNotEmpty(posCashier.getPassword())) {
            // 检查密码是否已经是BCrypt格式（以$2a$开头）
            if (!posCashier.getPassword().startsWith("$2a$")) {
                String encryptedPassword = SecurityUtils.encryptPassword(posCashier.getPassword());
                posCashier.setPassword(encryptedPassword);
                posCashier.setPwdUpdateDate(new Date());
            }
        }
        
        posCashier.setUpdateTime(new Date());
        return posCashierMapper.updatePosCashier(posCashier);
    }

    @Override
    public int deletePosCashierByCashierIds(Long[] cashierIds) {
        return posCashierMapper.deletePosCashierByCashierIds(cashierIds);
    }
}
